﻿namespace GoodAdmin.System;

public class BaseService : IBaseService, ITransient
{
    private readonly ISysRoleService _sysRoleService;
    private readonly ISysOrgService _sysOrgService;
    private readonly IRelationService _relationService;
    private readonly IRedisCacheManager _redisCacheManager;

    public BaseService(ISysRoleService sysRoleService, ISysOrgService sysOrgService,
        IRelationService relationService, IRedisCacheManager redisCacheManager)
    {
        _sysRoleService = sysRoleService;
        _sysOrgService = sysOrgService;
        _relationService = relationService;
        _redisCacheManager = redisCacheManager;
    }
    /// <inheritdoc/>
    public async Task<List<DataScope>> GetUserDataScope()
    {
        //先从缓存获取，如果有数据，直接返回
        string key = CacheConst.DataScope + UserManager.UserId;
        List<DataScope> scopes = _redisCacheManager.Get<List<DataScope>>(key);
        if (scopes != null) return scopes;

        scopes = new List<DataScope>();
        //获取用户拥有角色
        var roleList = await _sysRoleService.GetUserRoleList(UserManager.UserId);
        if (roleList == null)
        {
            //没有权限的同样存储，以免缓存穿透
            _redisCacheManager.Set(key, scopes);
            return scopes;
        }

        var orgList = await _sysOrgService.GetOrgList();
        var orgIdList = orgList.Select(o => o.Id).ToList();
        //超级管理员拥有所有数据范围权限
        if (roleList.Any(it => it.Code == RoleConst.SUPERADMIN))
        {
            scopes.Add(new DataScope { RouteUrl = RoleConst.SUPERADMIN, OrgList = orgIdList });
            _redisCacheManager.Set(key, scopes);
            return scopes;
        }
        //获取角色资源列表
        var resourceRealtion = await _relationService.GetRelationListByObjectIdList(CategoryConst.RELATION_ROLE_RESOURCE, roleList.Select(r => r.Id).ToList());
        if (resourceRealtion.Count == 0)
        {
            _redisCacheManager.Set(key, scopes);
            return scopes;
        }

        var resourceOutputList = resourceRealtion.Select(it => it.ExtraJson.ToJsonEntity<List<ResourceOutput>>());
        var resourceList = resourceOutputList.SelectMany(it => it).Distinct().ToList();
        //根据路由进行分组
        var resourceGroup = resourceList.GroupBy(it => it.ApiRoute).ToList();
        //循环添加数据范围
        //it表示路由
        resourceGroup.ForEach(it =>
        {
            HashSet<long> dataScope = new();
            //转换为列表
            var apiResourceList = it.ToList();
            //先判断是否有数据范围为全部的
            if (apiResourceList.Any(item => item.DataScopeType == RoleConst.DATA_SCOPE_ALL))
            {
                dataScope.AddRange(orgIdList);
                //添加一个顶级组织 id=0
                dataScope.Add(0);
            }
            //如果没有，那么则循环处理每个数据范围
            else
            {
                apiResourceList.ForEach(async item =>
                {
                    if (item.DataScopeType == RoleConst.DATA_SCOPE_SELF)//仅自己
                    {
                        return;
                    }
                    else if (item.DataScopeType == RoleConst.DATA_SCOPE_SELF)//仅本级组织
                    {
                        dataScope.Add(UserManager.OrgId);
                    }
                    else if (item.DataScopeType == RoleConst.DATA_SCOPE_ORG_CHILD)//本级以及下级组织
                    {
                        //获取所有下级
                        var childIdList = await _sysOrgService.GetOrgChildrenIdList(UserManager.OrgId);
                        dataScope.AddRange(childIdList);
                    }
                    else if (item.DataScopeType == RoleConst.DATA_SCOPE_DEFINE)//自定义组织
                    {
                        dataScope.AddRange(item.DefineScopeOrgList);
                    }
                });
            }
            scopes.Add(new DataScope { RouteUrl = it.Key, OrgList = dataScope.ToList() });
        });

        //根据userid使用string方式存储每个用户的数据范围
        _redisCacheManager.Set(key, scopes);
        return scopes;
    }

    /// <inheritdoc/>
    public async Task<List<long>> GetUserDataScopeByRequest()
    {
        //路由名称
        var routeName = App.HttpContext.Request.Path.Value;
        //获取用户数据范围
        var dataScopes = await GetUserDataScope();
        //根据请求路由查找数据范围
        //先筛选下是否有超管
        var dataScope = dataScopes.Any(d => d.RouteUrl == RoleConst.SUPERADMIN) ?
            dataScopes.Where(d => d.RouteUrl == RoleConst.SUPERADMIN).FirstOrDefault() : dataScopes.Where(d => d.RouteUrl == routeName).FirstOrDefault();
        var orgList = new List<long>();
        if (dataScope != null)
        {
            orgList.AddRange(dataScope.OrgList);
        }
        return orgList;
    }

    /// <inheritdoc/>
    public async Task CheckDataScope(long OrgId, long UserId = 0)
    {
        await CheckDataScope(new List<long> { OrgId });
    }

    /// <inheritdoc/>
    public async Task CheckDataScope(List<long> OrgIdList, long UserId = 0)
    {
        if (UserManager.SuperAdmin) return;
        var dataScope = await GetUserDataScopeByRequest();
        if (dataScope.Count == 0)
        {
            //如果没有资源数据范围权限，那么判断是否是当前操作人自己
            if (UserId > 0 && UserId != UserManager.UserId)
                throw Oops.Bah(OrgErrorCode.O007);
        }
        else if (!dataScope.ContainsAll(OrgIdList))
        {
            throw Oops.Bah(OrgErrorCode.O007);
        }
    }
}